package pe.com.bbva.pct.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pe.com.bbva.mtrgl.classLoader.AplicacionClassLoader;
import pe.com.bbva.pct.dao.ReglaFuenteDAO;
import pe.com.bbva.pct.dao.RelacionFuenteEntidadDAO;
import pe.com.bbva.pct.domain.Regla;
import pe.com.bbva.pct.domain.ReglaFuente;
import pe.com.bbva.pct.domain.RelacionFuenteEntidad;
import pe.com.bbva.pct.service.CoreMotorService;
import pe.com.bbva.pct.service.FuenteService;
import pe.com.bbva.pct.util.ConstantesGenerales;
import pe.com.bbva.pct.util.SpringJSFUtil;

import com.google.gson.Gson;

@Service("coreMotorService")
public class CoreMotorServiceImpl implements CoreMotorService{

	@Resource(name="relacionFuenteEntidadDao")
	private RelacionFuenteEntidadDAO relacionFuenteEntidadDao;
	
	@Resource(name="reglaFuenteDao")
	private ReglaFuenteDAO reglaFuenteDao;
	
	
	
	@Transactional(readOnly = true)
	@Override
	public List<Object> cargarFuentes(Regla objRegla) throws Exception{
		List<Object> listObject = new ArrayList<Object>();
		try {
			List<ReglaFuente> listaFuentesPorRegla = new ArrayList<ReglaFuente>();
			String nombre =objRegla.getIdAplicacion().getNombreCorto().trim().concat(objRegla.getIdAplicacion().getCodigo().trim());
			listaFuentesPorRegla = reglaFuenteDao.obtenerReglasFuenteEntrada(objRegla.getIdRegla());
			for(ReglaFuente fuente:listaFuentesPorRegla){
				List<Object> objetos = leerFuente(objRegla, fuente);
				listObject.addAll(objetos);
			}
			
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return listObject;
	}
	
	public List<Object> leerFuente(Regla objRegla, ReglaFuente fuente){
		List<Object> objetos = new ArrayList<Object>();
 		try {
			List<RelacionFuenteEntidad>  listaRelaciones = relacionFuenteEntidadDao.obtenerRelacionFuenteEntidad(fuente.getIdReglaFuente());
			switch(Integer.parseInt(fuente.getIdFuente().getIdTipoFuente().getIdValor().toString())){
			case 5: /*tipo txt*/
				File file = new File(fuente.getIdFuente().getRutaArchivo()); 
			    if (file.exists()){
			    	BufferedReader entrada = new BufferedReader(new FileReader(file));
			    	String linea;
			    	
			    	while ((linea = entrada.readLine()) != null) { 
			    		Object objeto;
			    		Class c = null;
						AplicacionClassLoader app=SpringJSFUtil.getBean("aplicacionClassLoader");
						c = app.getClassPathApp(objRegla.getIdAplicacion().getNombreCorto().trim().concat(objRegla.getIdAplicacion().getCodigo().trim())).loadClass(fuente.getClaseEntidad());	          
						objeto = c.newInstance();
			    		Class objClass = objeto.getClass();
			    		
			    		for(RelacionFuenteEntidad relacion : listaRelaciones){
			    			
			    			Field field = objClass.getDeclaredField(relacion.getCampoEntidad().trim());
			    			field.setAccessible(true);
			    			String value = linea.substring(Integer.parseInt(relacion.getIdDetalleFuente().getInicio().toString()),
									 Integer.parseInt(relacion.getIdDetalleFuente().getInicio().toString())+
									 Integer.parseInt(relacion.getIdDetalleFuente().getLongitud().toString()));
			    			System.out.println(value);
			    			if (relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_INTEGER){
			    				field.set(objeto,Integer.parseInt(value.trim()));
			    			}else if(relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_STRING){
			    				field.set(objeto,value.toString().trim());
			    			}else if(relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_DECIMAL){
			    				field.set(objeto,Double.parseDouble(value.trim()));
			    			}else if(relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_DATE){
			    				SimpleDateFormat sdf1 = new SimpleDateFormat("dd/MM/yyyy");;
			    				Date date = sdf1.parse(value.trim());
			    				field.set(objeto,date);
			    			}
			    			
			    		}
			    		Gson json = new Gson();
			    		
			    		System.out.println(json.toJson(objeto));
			    		objetos.add(objeto);
			    	}
			    }
				break;
			case 4: /*tipo tabla*/
				
				
				FuenteService fuenteService=SpringJSFUtil.getBean("fuenteService");
				ArrayList<HashMap<String, Object>>  Registros = fuenteService.ejecutarConsulta(fuente.getIdFuente().getNombreJndi(), fuente.getIdFuente().getConsulta());
				 for(HashMap<String, Object> objetoMap : Registros){
					
					 	Object objeto;
			    		Class c = null;
						AplicacionClassLoader app=SpringJSFUtil.getBean("aplicacionClassLoader");
						c = app.getClassPathApp(objRegla.getIdAplicacion().getNombreCorto().trim().concat(objRegla.getIdAplicacion().getCodigo().trim())).loadClass(fuente.getClaseEntidad());	          
						objeto = c.newInstance();
			    		Class objClass = objeto.getClass();
					 
					 for(RelacionFuenteEntidad relacion : listaRelaciones){
			    			
			    			Field field = objClass.getDeclaredField(relacion.getCampoEntidad().trim());
			    			field.setAccessible(true);
			    			String value=null;
			    			if(objetoMap.get(relacion.getCampoFuente()).getClass().equals(BigDecimal.class)){
			    				value=""+objetoMap.get(relacion.getCampoFuente())+"";
			    			}else if(objetoMap.get(relacion.getCampoFuente()).getClass().equals(java.sql.Date.class)){
			    				
			    				value=""+objetoMap.get(relacion.getCampoFuente())+"";
			    			}else{
			    				 value = (String) objetoMap.get(relacion.getCampoFuente().trim());
			    			}
			    			
			    		
			    			if (relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_INTEGER){
			    				field.set(objeto,Integer.parseInt(value.trim()));
			    			}else if(relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_STRING){
			    				field.set(objeto,value.toString().trim());
			    			}else if(relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_DECIMAL){
			    				field.set(objeto,Double.parseDouble(value.trim()));
			    			}else if(relacion.getIdDetalleFuente().getIdTipoDato().getIdValor() == ConstantesGenerales.TIPO_DATE){
			    				value=value.trim().replace("-", "/");
			    				SimpleDateFormat sdf1 = new SimpleDateFormat("dd/MM/yyyy");;
			    				Date date = sdf1.parse(value.trim());
			    				field.set(objeto,date);
			    			}
			    			
			    		}
			    		Gson json = new Gson();
			    		objetos.add(objeto);
				 }
				 
				 
				 break;
		}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return objetos;
	}
	
	@SuppressWarnings("unused")
	public Object instanciarObjeto(String claseEntidad, Regla objRegla) throws Exception{
	 Object objeto = null;
		try {
			/* Generando la instancia de la clase programada en la fuente*/
			Class c = null;
			AplicacionClassLoader app=SpringJSFUtil.getBean("aplicacionClassLoader");
			c = app.getClassPathApp(objRegla.getIdAplicacion().getNombreCorto().trim().concat(objRegla.getIdAplicacion().getCodigo().trim())).loadClass(claseEntidad);	          
			objeto = c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return objeto;
	}
	
	
}
